﻿using System;
using System.ComponentModel;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Threading;
using SharpDX.XAudio2;
using SynergyLib.Wave;

namespace XAudio2Controls
{
    /// <summary>
    /// Base classes for the control that holds individual patches.
    /// 
    /// stuff that needs attention:
    /// 
    /// **ListBoxPatches Event Handlers not implemented
    /// </summary>
    public abstract class XA2PatchBase : CustomControlBase, INotifyPropertyChanged
    {
        internal enum CurrentlySelectedTab
        {
            Patch,
            Shape,
            Submixer,
            Pattern,
            Effects
        }
        #region fields
        /// <summary>
        /// miniSpectrumAnalyzerHolder has no xaml counterpart
        /// </summary>
        internal Grid miniSpectrumAnalyzerHolder;
        protected Label LabelPatchControl { get { return ResourceRoot.FindName("PART_LabelPatchControl") as Label; } }
        protected ListBox ListBoxPatches { get { return ResourceRoot.FindName("PART_ListBoxPatches") as ListBox; } }
        protected Button ButtonNewPatch { get { return ResourceRoot.FindName("PART_ButtonNewPatch") as Button; } }
        protected Button ButtonRemovePatch { get { return ResourceRoot.FindName("PART_ButtonRemovePatch") as Button; } }       
        protected Grid TabControlGrid { get { return ResourceRoot.FindName("PART_TabControlGrid") as Grid; } }
        internal ObservableCollection<Control> Patches = new ObservableCollection<Control>();
        internal Thread PatchControlThread;
        #endregion fields

        #region Properties
        public bool BarsGroupedToPhrase
        {
            get;
            protected set;
        }
        #endregion Properties

        #region Dependency Properties
        public static readonly DependencyProperty NumberOfBarsProperty =
          DependencyProperty.Register("NumberOfBars", typeof(int), typeof(XA2PatchBase), new PropertyMetadata(new PropertyChangedCallback(NumberOfBarsChanged)));
        private static void NumberOfBarsChanged(DependencyObject dependency, DependencyPropertyChangedEventArgs args)
        {
            XA2PatchBase instance = dependency as XA2PatchBase;
            if (instance != null)
            {
                instance.NotifyPropertyChanged("NumberOfBars");
            }
        }
        [Category("Common")]
        public int NumberOfBars
        {
            get { return (int)GetValue(NumberOfBarsProperty); }
            protected set
            {
                SetValue(NumberOfBarsProperty, value);
            }
        }

        #region Orientation

        
        
            
        #endregion Orientation
        #endregion Dependency Properties

        #region Constructor
        protected XA2PatchBase()
        {
           /*
                if (PatchControlThread == null)
                {
                    PatchControlThread = Thread.CurrentThread;
                    PatchControlThread.Name = "PatchControlThread";
                }
            */
            Patches.CollectionChanged += Patches_CollectionChanged;
        }

        
        #endregion Constructor

        #region Methods
        internal override void GetTemplateChildren()
        {
            if (miniSpectrumAnalyzerHolder == null)
            {
                miniSpectrumAnalyzerHolder = new Grid();
            }
            LabelPatchControl.Content = "[" + this.ToString() + "]";
            ListBoxPatches.SelectionChanged += new SelectionChangedEventHandler(ListBoxPatches_SelectionChanged);
            ButtonNewPatch.Click += new RoutedEventHandler(ButtonNewPatch_Click);
            ButtonRemovePatch.Click += new RoutedEventHandler(ButtonRemovePatch_Click);
        }
        internal bool TabShapeHasMiniSpectrum()
        {
            if (Patches.Count > 0)
            {
                foreach (XA2TabPanelBase tpb in Patches)
                {
                    if (tpb.TabShapePanel.Children.Contains(DrumPatchControl.DynamicSpectrumAnalyzer))
                        tpb.TabShapePanel.Children.Clear();
                }
                return true;
            }
            return false;
        }
        private void RemoveChild(XA2TabPanelBase child)
        {
            Patches.Remove(child);
            TabControlGrid.Children.Clear();            
            child.Dispose();
        }
        #endregion Methods

        #region Event Handlers  
        public override void OnApplyTemplate()
        {
            try
            {
                ScheduledXAudio2.Engine.BPMChangeNotifier.PropertyChanged += BPMChangeNotifier_PropertyChanged;
            }
            catch (NullReferenceException)
            {
                Console.WriteLine("NullReferenceException in OnApplyTemplate() in XA2PatchBase");
            }
            //base.OnApplyTemplate();
        }
        protected virtual void ButtonRemovePatch_Click(object sender, RoutedEventArgs e)
        {
            
            if (ListBoxPatches.SelectedItem != null)
            {
                var child = ListBoxPatches.SelectedItem as XAudio2Controls.XA2TabPanelBase;
                //results in an acessviolationexception in drumpatchinstance
                //child.Dispose();
                child.IsEnabled = false;
                RemoveChild(child);                
            }
            if (ListBoxPatches.Items.Count > 0)
                ListBoxPatches.SelectedIndex = ListBoxPatches.Items.Count - 1;
        }
        protected virtual void ButtonNewPatch_Click(object sender, RoutedEventArgs e)
        {

        }
        protected virtual void ListBoxPatches_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (ListBoxPatches.SelectedValue != null)
            {
                var selection = ListBoxPatches.SelectedValue as XA2TabPanelBase;
                if (TabControlGrid != null)
                {
                    if (TabControlGrid.Children != null)
                        TabControlGrid.Children.Clear();
                    if (selection != null)
                    {
                        selection.WasSelected_OnRaiseEvent(new RoutedEventArgs());
                        TabControlGrid.Children.Add(selection);
                    }
                }
            }
        }
        protected void Patches_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
           
        }
        protected void BPMChangeNotifier_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            try
            {
                var v = ScheduledXAudio2.Engine.BPMChangeNotifier as SynergyControls.BPM_Slider;
                ScheduledXAudio2.Engine.Scheduler.BeatsPerMinute = v.BPM;
            }
            catch (NullReferenceException ex)
            {
                System.Windows.MessageBox.Show
                    ((ex.Message + "\n" + ex.StackTrace)
                    + "\n \n You probably tried changing the bpm before there is anything to change. try again after adding some patches", "tempo is null");
            }
        }
        
        
        #endregion Event Handlers

        #region INotifyPropertyChanged

        public event PropertyChangedEventHandler PropertyChanged;

        protected void NotifyPropertyChanged(String info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }

        #endregion
}}

